﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Xml;
using SdmxMl.Helper;
using SdmxMl.Common;

namespace SdmxMl.Structure
{
    /// <summary>
    /// LevelType describes a level in a hierarchical codelist. The Order element
    /// specifies where the level is in a levelled hierarchy, starting with the
    /// value "1" for the top level, and going sequentially from there using whole
    /// integers. CodingType specifies the text formatting of the codes at that level.
    /// A human-readable name must be assigned, which may be provided in multiple,
    /// parallel-language versions. A longer, human-readable Description may also
    /// be provided, which can also have multiple parallel-language versions.
    /// Annotations may be provided with the Annotations element. The id attribute
    /// provides a unique id for the hierarchy. The urn attribute can be used to
    /// specify the hierarchy with a valid SDMX Registry URN (see the SDMX Registry Specification).
    /// </summary>
    public class LevelType: BaseArtefact
    {

        #region Properties

        // Inherited version should not be used.

        /// <summary>
        /// The uri attribute holds a URI that contains a link to a resource with additional information
        /// about the object, such as a web page. This uri is not a SDMX message.
        /// </summary>
        public string Uri { get; set; }
        public string Urn { get; set; }

        private int _order;
        public int Order
        {
            get { return _order; }
            set { _order = value; }
        }

        protected TextFormatType _codingType;
        public TextFormatType CodingType
        {
            get { return _codingType; }
            set { _codingType = value; }
        }
 
        #endregion //Properties

        #region Constructors

        public LevelType()
        {
            _codingType = new TextFormatType();
        }

        // Clone c'tor
        public LevelType(LevelType clone)
        {
            Id = clone.Id;
            Version = clone.Version;
            Name = new MultiLang(clone.Name);
            Description = new MultiLang(clone.Description);
            Urn = clone.Urn;
            _order = clone.Order;
            _codingType = new TextFormatType(clone.CodingType);
            AnnotationList = clone.AnnotationList.Clone();
        }

        public LevelType(XmlNode nodeArtefact, SdmxNamespaceManager nsmgr) 
            : base(nodeArtefact, nsmgr)
        { 
            Urn = Xmlhelper.GetAtt(nodeArtefact, "urn");
            string s = Xmlhelper.GetNodeText(nodeArtefact, "./structure:Order", nsmgr);
            if (s.Length > 0)
                _order = Convert.ToInt32(s);
            _codingType = new TextFormatType(nodeArtefact, "./structure:CodingType", nsmgr);

        }

        #endregion //Constructors

        #region XML Representation

        public void WriteHierarchizedLevel_21(XmlTextWriter xw, string prefix, string tag)
        {
            xw.WriteStartElement(prefix, tag, null);
            // value required
            xw.WriteAttributeString("id", Id);
            Xmlhelper.WriteAttributeIfExist(xw, "urn", Urn);
            Xmlhelper.WriteAttributeIfExist(xw, "uri", Uri);

            // Annotations
            AnnotationList.WriteXml(xw, prefix, null);

            Name.WriteXml(xw, prefix, "Name");
            Description.WriteXml(xw, prefix, "Description");

            // Text Format
              if (_codingType.TextType != TextTypeType.Undefined)
                  _codingType.WriteXmlAsSimpleCodeDataType(xw, prefix, "CodingFormat");

        }

        public void WriteXml(XmlTextWriter xw, string prefix, string tag)
        {
            if (SdmxNamespaceManager.SdmxTarget == SdmxVersion.SDMX_20)
            {
                xw.WriteStartElement(prefix, tag, null);

                // value required
                xw.WriteAttributeString("id", Id);
                Xmlhelper.WriteAttributeIfExist(xw, "urn", Urn);

                Name.WriteXml(xw, prefix, "Name");
                Description.WriteXml(xw, prefix, "Description");

                // Order required
                xw.WriteElementString(prefix, "Order", null, Order.ToString());

                // Text Format
                if (_codingType.TextType != TextTypeType.Undefined)
                    _codingType.WriteXml(xw, prefix, "CodingType");

                // Annotations
                AnnotationList.WriteXml(xw, prefix, null);

                xw.WriteEndElement();
            }
        }

        #endregion // XML Representation

    }

    public class LevelTypeList : List<LevelType>
    {
        public string GetIdOfOrder(int order)
        {
            foreach (LevelType lv in this)
                if (lv.Order == order)
                    return lv.Id;
            return string.Empty;
        }

        // Deep Copy
        public LevelTypeList Clone()
        {
            LevelTypeList lvt = new LevelTypeList();
            foreach (LevelType lv in this)
                lvt.Add(new LevelType(lv));

            return lvt;
        }

        protected DataTable DefineDataTableRepresentation()
        {
            DataTable dataTable = new DataTable();
            dataTable.Columns.Add(new DataColumn("Ref", typeof(bool)));
            dataTable.Columns.Add(new DataColumn("Id", typeof(string)));
            dataTable.Columns.Add(new DataColumn("Order", typeof(string)));
            dataTable.Columns.Add(new DataColumn("Name", typeof(string)));
            dataTable.Columns.Add(new DataColumn("Coding", typeof(string)));
            return dataTable;
        }

        public List<object> GetRowObjects(LevelType lv)
        {
            List<object> lo = new List<object>(5);

            lo.Add(true);
            lo.Add(lv.Id);
            lo.Add(lv.Order.ToString());
            lo.Add(lv.Name.ToString());
            lo.Add(lv.CodingType.ToString());

            return lo;
        }


        public DataTable GetTableRepresentation()
        {
            DataTable dataTable = DefineDataTableRepresentation();

            foreach (LevelType lv in this)
                dataTable.Rows.Add(GetRowObjects(lv).ToArray());

            return dataTable;
        }

    }
}
